package com.icw.configuration.web.api;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.icw.configuration.data_interchange.RpcResult;
import com.icw.decoupling.defi.proxy.RestfulApiProxy;
import com.icw.utility.IcwUtils;
import com.icw.utility.PoEntityHelper;

@RestController
@RequestMapping("/resource")
public class RestfulFormApi {

	@Autowired
	private RestfulApiProxy api;

	@GetMapping(value = { "/{srcName}/getone/{id}", "/{srcName}/getone/" })
	public void getone(@PathVariable("srcName") String srcName, @PathVariable(value = "id", required = false) String id, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.getone(srcName, idParams(id, null), request, response, out);
	}

	@PostMapping(value = "/{srcName}/getlist", headers = { "Accept=application/json" })
	public void getlist(@PathVariable("srcName") String srcName, @RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.getlist(srcName, params, request, response, out);
	}

	@PostMapping(value = "/{srcName}/exists", headers = { "Accept=application/json" })
	public void exists(@PathVariable("srcName") String srcName, @RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.exists(srcName, params, request, response, out);
	}

	@Deprecated
	@PostMapping(value = "/{srcName}/getexcel", headers = { "Accept=application/json" })
	public void getexcel(@PathVariable("srcName") String srcName, @RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.getexcel(srcName, params, request, response, out);
	}

	@PostMapping(value = "/{srcName}/post", headers = { "Accept=application/json" })
	public void post(@PathVariable("srcName") String srcName, @RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.post(srcName, idParams(null, params), request, response, out);
	}

	@PatchMapping(value = { "/{srcName}/patch/{id}", "/{srcName}/patch/" }, headers = { "Accept=application/json" })
	public void patch(@PathVariable("srcName") String srcName, @PathVariable(value = "id", required = false) String id, @RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.patch(srcName, idParams(id, params), request, response, out);
	}

	@DeleteMapping(value = { "/{srcName}/delete/{id}", "/{srcName}/delete/" })
	public void delete(@PathVariable("srcName") String srcName, @PathVariable(value = "id", required = false) String id, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		api.delete(srcName, idParams(id, null), request, response, out);
	}

	@PostMapping(value = { "/any/batch" }, headers = { "Accept=application/json" })
	public void batch(@RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, Map<String, Object> out) throws Exception {
		Object[] actions = PoEntityHelper.toObjectArray(params.get("actions"));
		for (int i = 0; i < actions.length; i++) {
			Object action = actions[i];
			try {
				PoEntityHelper.writeValueByProperty(action, "res", new RpcResult(true, null, IcwUtils.mapObject()));
				String resourceName = (String) PoEntityHelper.readValueByProperty(action, "resourceName");
				String method = (String) PoEntityHelper.readValueByProperty(action, "method");
				@SuppressWarnings("unchecked")
				Map<String, Object> eachParams = (Map<String, Object>) PoEntityHelper.readValueByProperty(action, "params");
				@SuppressWarnings("unchecked")
				Map<String, Object> output = (Map<String, Object>) PoEntityHelper.readValueByProperty(action, "res.data");
				if (method.equals("getone")) {
					api.getone(resourceName, atMostJustId(eachParams), request, response, output);
				} else if (method.equals("getlist")) {
					api.getlist(resourceName, eachParams, request, response, output);
				} else if (method.equals("post")) {
					api.post(resourceName, eachParams, request, response, output);
				} else if (method.equals("patch")) {
					api.patch(resourceName, eachParams, request, response, output);
				} else if (method.equals("delete")) {
					api.delete(resourceName, atMostJustId(eachParams), request, response, output);
				} else if (method.equals("exists")) {
					api.exists(resourceName, eachParams, request, response, output);
				} else {
					throw new Exception("No action found");
				}
			} catch (Exception e) {
				PoEntityHelper.writeValueByProperty(action, "res", new RpcResult(e));
			}
		}
		out.put("actions", actions);
	}

	private static Map<String, Object> idParams(String id, Map<String, Object> params) {
		if (params == null) {
			params = IcwUtils.mapObject("id", id);
		}
		if (id == null) {
			params.remove("id");
		}
		return params;
	}

	private Map<String, Object> atMostJustId(Map<String, Object> eachParams) {
		return eachParams.containsKey("id") ? IcwUtils.mapObject("id", eachParams.get("id")) : IcwUtils.mapObject();
	}
}
